#include "bsp_key.h"

void BSP_Key_Init(Button_t* Button)
{
    Button[0].ButtonFlag = Flag_IDLE;
    Button[0].ButtonState = IDLE_STATE;
    Button[0].ButtonHardware.Key_Port = KEY1_GPIO_Port;
    Button[0].ButtonHardware.Key_Pin = KEY1_Pin;
    Button[0].SHORT_CLICK_THRESHOLD = 400;
    Button[0].LONG_PRESS_THRESHOLD = 1000;
    Button[0].PRESS_Time = 100;
    Button[0].BUTTON_ERROR_Time = 1500;

    Button[1].ButtonFlag = Flag_IDLE;
    Button[1].ButtonState = IDLE_STATE;
    Button[1].ButtonHardware.Key_Port = KEY2_GPIO_Port;
    Button[1].ButtonHardware.Key_Pin = KEY2_Pin;
    Button[1].SHORT_CLICK_THRESHOLD = 400;
    Button[1].LONG_PRESS_THRESHOLD = 1000;
    Button[1].PRESS_Time = 100;
    Button[1].BUTTON_ERROR_Time = 1500;

    Button[2].ButtonFlag = Flag_IDLE;
    Button[2].ButtonState = IDLE_STATE;
    Button[2].ButtonHardware.Key_Port = KEY3_GPIO_Port;
    Button[2].ButtonHardware.Key_Pin = KEY3_Pin;
    Button[2].SHORT_CLICK_THRESHOLD = 400;
    Button[2].LONG_PRESS_THRESHOLD = 1000;
    Button[2].PRESS_Time = 100;
    Button[2].BUTTON_ERROR_Time = 1500;

    Button[3].ButtonFlag = Flag_IDLE;
    Button[3].ButtonState = IDLE_STATE;
    Button[3].ButtonHardware.Key_Port = KEY4_GPIO_Port;
    Button[3].ButtonHardware.Key_Pin = KEY4_Pin;
    Button[3].SHORT_CLICK_THRESHOLD = 400;
    Button[3].LONG_PRESS_THRESHOLD = 1000;
    Button[3].PRESS_Time = 100;
    Button[3].BUTTON_ERROR_Time = 1500;
}

void Key_Loop(Button_t* Button, uint16_t key_value, uint8_t action)
{
    GPIO_PinState keyStatus =
        HAL_GPIO_ReadPin(Button->ButtonHardware.Key_Port, Button->ButtonHardware.Key_Pin);  // 检测按键
    uint32_t currentTime = HAL_GetTick();
    switch(Button->ButtonState)
    {
        case IDLE_STATE:
            if(keyStatus == 0)  // 如果按键按下
            {
                Button->ButtonState = PRESS_DETECTED_STATE;  // 切换到按键按下状态
                Button->pressStartTime = currentTime;        // 记录按下时间
            }
            break;

        case PRESS_DETECTED_STATE:  // 按键 按下状态
            if(keyStatus == 1)      // 检测按键松开时间
            {
                Button->ReleaseTime = currentTime;             // 记录按键放松时间
                Button->ButtonState = RELEASE_DETECTED_STATE;  // 如果按下后释放则进入这里
            }
            else if(currentTime - Button->pressStartTime
                    > Button->LONG_PRESS_THRESHOLD)  // 判断按键长按的时长如果符合则跳转到这里。
            {
                Button->ButtonState = LONG_PRESS_STATE;
            }
            else if(currentTime - Button->pressStartTime > Button->BUTTON_ERROR_Time)  // 防止按键卡死
            {
                Button->ButtonState = IDLE_STATE;
            }
            break;
        case LONG_PRESS_STATE_END:  // 长按结束后的状态跳转这里等待按键松开 防止一直处于长按状态   /
            if(keyStatus == 1)
            {
                Button->ButtonState = IDLE_STATE;
            }
            break;

        case RELEASE_DETECTED_STATE:  // 按键释放过后的状态
            if((keyStatus == 0)
               && (currentTime - Button->ReleaseTime
                   < Button->SHORT_CLICK_THRESHOLD))  // 如果按键再次按下并且第二次时长是在500ms以内按下的
            {
                Button->ButtonState = DOUBLE_PRESS_STATE;
            }
            else if((Button->ReleaseTime - Button->pressStartTime > Button->PRESS_Time)
                    && (currentTime - Button->ReleaseTime
                        > Button->SHORT_CLICK_THRESHOLD))  // 判断按键按下时长防止毛刺 在判断当前是否在双击范围内
            {
                Button->ButtonState = SHORT_PRESS_STATE;
            }
            else if(currentTime - Button->ReleaseTime > Button->BUTTON_ERROR_Time)  // 按键出现无法判断情况回到初态
            {
                Button->ButtonState = IDLE_STATE;
            }
            break;

        case SHORT_PRESS_STATE:
            key_value = action;
            Button->ButtonFlag = Flag_IDLE;
            Button->ButtonState = LONG_PRESS_STATE_END;
            break;

        case LONG_PRESS_STATE:
            Button->ButtonFlag = Flag_IDLE;
            Button->ButtonState = LONG_PRESS_STATE_END;
            break;

        case DOUBLE_PRESS_STATE:
            Button->ButtonFlag = Flag_IDLE;
            Button->ButtonState = LONG_PRESS_STATE_END;
            break;
        default:
            break;
    }
}

__weak void USER_Key1_Callback() {}

__weak void USER_Key2_Callback() {}

__weak void USER_Key3_Callback() {}

__weak void USER_Key4_Callback() {}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == KEY1_Pin)
    {
        USER_Key1_Callback();
    }

    if(GPIO_Pin == KEY2_Pin)
    {
        USER_Key2_Callback();
    }

    if(GPIO_Pin == KEY3_Pin)
    {
        USER_Key3_Callback();
    }

    if(GPIO_Pin == KEY4_Pin)
    {
        USER_Key4_Callback();
    }
}
